#include <stdio.h>
#include <stdlib.h>

#include "ListIter.h"

/**     struct Person & Match func    **/
typedef struct Person_t
{
    int age;
    int id;
    char name[200];
}Person;

int IsPersonMatch(Person* _data, void* _param)
{
 return (_data)->age == *((int*)_param);
}
/***************************************/


/***************************************************************************************************************/
/*********************************************    LIST_UTEST    *************************************************/
/***************************************************************************************************************/
#define IS_SUCCESS(X) !X?"SUCCESS":"FAILURE"   /*  Macro to print on regression tests       */
#define IF_FAIL(X) if(X){printf("FAIL IN %s TEST, IN LINE %d\n",#X,__LINE__); return 1;}
/*******************    Forward Declerations    ******************/
int ListRegression_Utest();
int ListBeginEnd_Utest();
int ListInsert_Utest();
int ListNextPrev_Utest();
int ListRemove_Utest();
/*****************************************************************/

int ListRegression_Utest()
{
    printf("ListBeginEnd_Utest: %s\n\n", IS_SUCCESS(ListBeginEnd_Utest()));
    printf("ListInsert_Utest: %s\n\n", IS_SUCCESS(ListInsert_Utest()));
    printf("ListNextPrev_Utest: %s\n\n", IS_SUCCESS(ListNextPrev_Utest()));
    printf("ListRemove_Utest: %s\n", IS_SUCCESS(ListRemove_Utest()));

    return 0;
}

int main()
{
    ListRegression_Utest();

    return 0;
}

int ListBeginEnd_Utest()
{
    List* list = ListNew();
    void* data;

    IF_FAIL(ListBegin(list) != ListEnd(list))   /*  Check that begin == end at start (tail)    */
    data = ListGetData(ListBegin(list));        /*  Check the intial data                       */
    IF_FAIL(data != (void*)0xdeadbeef)
    ListDelete(list);

    return 0;
}

int ListInsert_Utest()
{
    List* list = ListNew();
    Person p1 = {30, 555,"yoav"};
    Person p2 = {60, 666,"duby"};
    Person p3 = {90, 777,"miko"};
    Iter it1;
    Iter it2;
    Iter it3;

    IF_FAIL(!ListIsEmpty(list))                  /*  Check list empty           */
    ListInsert(ListBegin(list),&p1);            /*  Insert p1 to begin          */
    IF_FAIL(ListIsEmpty(list))                  /*  Check not empty             */
    it1 = ListBegin(list);                       /*  Get iterator to begin       */
    IF_FAIL(&p1 != (Person*)ListGetData(it1))    /*  Check that realy inserted   */
    it2 = ListInsert(it1,&p2);                    /*  Insert p2 to the iterator   */
    IF_FAIL(&p2 != (Person*)ListGetData(it2))    /*  Check the it return         */
    it3 = ListInsert(it2,&p3);                    /*  Insert p2 to the iterator   */
    IF_FAIL(&p3 != (Person*)ListGetData(it3))    /*  Check the it return         */
    ListDelete(list);

    return 0;
}

int ListNextPrev_Utest()
{
    List* list = ListNew();
    Person p1 = {30, 555,"yoav"};
    Person p2 = {60, 666,"duby"};
    Person p3 = {90, 777,"miko"};
    Iter it1;
    Iter it2;
    Iter it3;

    ListInsert(ListBegin(list),&p1);            /*  Insert p1 to begin          */
    it1 = ListBegin(list);                       /*  Get iterator to begin       */
    IF_FAIL(ListNext(it1) != ListEnd(list))     /*  Check the next is end   */
    it2 = ListInsert(it1,&p2);                    /*  Insert p2 to the iterator   */
    IF_FAIL(ListPrev(it1) != it2)
    it3 = ListInsert(it1,&p3);                    /*  Insert p2 to the iterator   */
    IF_FAIL(ListNext(it3) != it1 && ListPrev(it3) != it2)   /*  The order should be it2 , it3 , it1 */
    ListDelete(list);

    return 0;
}

int ListRemove_Utest()
{
    List* list = ListNew();
    Person p1 = {30, 555,"yoav"};
    Person p2 = {60, 666,"duby"};
    Person p3 = {90, 777,"miko"};
    Iter it1;
    Iter it2;
    Iter it3;

    ListInsert(ListBegin(list),&p1);            /*  Insert p1 to begin          */
    it1 = ListBegin(list);                       /*  Get iterator to begin       */
    it2 = ListInsert(it1,&p2);                    /*  Insert p2 to the iterator   */
    ListRemove(it2);
    IF_FAIL(ListCount(list) != 1)                   /*  Check only one is there */
    IF_FAIL(ListGetData(ListBegin(list)) != &p1)    /*  After remove it2, begin is p1   */
    it3 = ListInsert(it1,&p3);                    /*  Insert p2 to the iterator   */
    ListRemove(it3);
    ListRemove(ListBegin(list));
    IF_FAIL(!ListIsEmpty(list))

    ListDelete(list);


    return 0;
}
